package com.googlecode.archimedes.filegen.generator.freemarker;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.Charset;

import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.googlecode.archimedes.filegen.controller.GenerationException;
import com.googlecode.archimedes.filegen.generator.AbstractGenerator;
import com.googlecode.archimedes.filegen.template.Template;

import freemarker.core.ParseException;
import freemarker.template.Configuration;
import freemarker.template.SimpleHash;
import freemarker.template.TemplateException;

/**
 * <p>
 * Largely this is a Copy of the VelocityGenerator.java The common lines/methods have been noted and should be moved into a common class. This Class
 * generates a single file from a FreeMarker Template
 * </p>
 * <p>
 * Created: Jan 13, 2005
 * </p>
 * 
 * @author John Lema
 * @version $Id: FreeMarkerGenerator.java 2017 2006-02-17 02:01:34 +0000 (Fri, 17 Feb 2006) jeremyw $
 */
public class FreeMarkerGenerator {

	private static Log	log	= LogFactory.getLog(FreeMarkerGenerator.class);

	// ----- Main Method -----------------------------------------------------------

	/**
	 * Adapter method to introduce the "subpath" value to the generation code
	 */
	protected static void generate(AbstractGenerator generator, String objectName, Template template, SimpleHash dataModel) throws GenerationException {
		generate(generator, objectName, template, dataModel, "");
	}

	/**
	 * Generates files
	 */
	protected static void generate(AbstractGenerator generator, String objectName, Template template, SimpleHash dataModel, String subpath) throws GenerationException {
		try {

			// setup FreeMarker
			Configuration cfg = Configuration.getDefaultConfiguration();
			File templDir = getTemplateDirectory(generator);
			cfg.setDirectoryForTemplateLoading(templDir);

			// locate the template
			freemarker.template.Template currentTemplate = cfg.getTemplate(template.getTemplateName() + ".ftl");
			log.debug("Using a template [" + template.getTemplateName() + ".ftl" + "]");

			// make sure object name is a valid string
			objectName = (objectName == null) ? "" : objectName;
			String outputFileName = template.resolveFileName(new Object[] { objectName }) + template.getExtension();
			String outputPath = generator.getOutputDirectoy() + template.getOutputPath();

			if (!template.isFlat()) {
				outputPath += subpath;
			}

			// generate the new content
			StringWriter writer = new StringWriter();
			currentTemplate.process(dataModel, writer);
			String newContent = writer.toString();

			// define the file we want to generate
			log.debug("Generating file [" + outputPath + outputFileName + "].");
			File targetFile = new File(outputPath, outputFileName);

			if (targetFile.exists() && !template.isOverwriteAllowed()) {
				log.info("Skipping [" + targetFile.getAbsolutePath() + "] -- file exists and the template [" + template.getTemplateName() + "] does not allow overwriting.");
				return;
			}

			buildTree(targetFile);

			// read in the old content - leave null
			String oldContent = targetFile.exists() ? FileUtils.readFileToString(targetFile, Charset.defaultCharset().name()) : null;

			// if the oldContent is null (new creation) or the oldContent is different from the new content, write our file.
			if (oldContent == null || !oldContent.equals(newContent)) {
				FileUtils.writeStringToFile(targetFile, newContent, Charset.defaultCharset().name());
			}

		} catch (TemplateException e) {
			log.error("FreeMarkerTemplate : error : Error in the template [" + template.getTemplateName() + "]", e);
			throw new GenerationException(e);
		} catch (ParseException e) {
			log.error("FreeMarkerTemplate : Error Parsing the Template [" + template.getTemplateName() + "]", e);
			throw new GenerationException(e);
		} catch (IOException e) {
			log.error("FreeMarkerTemplate : Syntax error with template [" + template.getTemplateName() + "]", e);
			throw new GenerationException(e);
		} catch (Exception e) {
			throw new GenerationException(e);
		}
	}

	// ----- Utility Methods -----------------------------------------------------------

	/**
	 * This returns the location of the directory where the freemarker Templates are stored
	 */
	protected static File getTemplateDirectory(AbstractGenerator generator) {
		log.debug("Using the path [" + generator.getResourceDirectory());
		return new File(generator.getResourceDirectory());
	}

	/**
	 * This is an Copy of the Same method in VelocityGenerator - A common parent class should be built There are no differences
	 * 
	 * @see com.tps.filegen.template.Generateable#getProperties()
	 */
	protected static void buildTree(File file) {
		// find the parent of the file in question
		File parent = file.getParentFile();

		// create the parent & any directories needed
		parent.mkdirs();
	}
}